package com.zhb.cloud.controller;

import static org.elasticsearch.common.xcontent.XContentFactory.*;
import static org.elasticsearch.index.query.QueryBuilders.*;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.bulk.BackoffPolicy;
import org.elasticsearch.action.bulk.BulkProcessor;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetItemResponse;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.MultiSearchResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;

import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryAction;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.script.mustache.SearchTemplateRequestBuilder;
import org.elasticsearch.search.SearchHit;
import static org.elasticsearch.search.aggregations.AggregationBuilders.*;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.zhb.cloud.model.User;
import com.zhb.cloud.service.UserService;

@RestController
@RequestMapping("user")
@SuppressWarnings("all")
public class UserController {
	private Logger logger = LoggerFactory.getLogger(UserController.class);
	@Autowired
	private UserService userService;
	@Autowired
	private TransportClient transportClient;

	@RequestMapping("addIndex")
	public String AddIndex() throws IOException {
		IndexRequestBuilder prepareIndex = transportClient.prepareIndex("users", "user");
		/**
		 * 使用es的拼接方式
		 */
		for (int i = 0; i < 10; i++) {
			int gender = 0;
			if (i % 2 == 1) {
				gender = 1;
			}
			XContentBuilder xContentBuilder = jsonBuilder().startObject().field("id", i)
					.field("registerTime", new Date()).field("phone", "1581190211" + i).field("realName", "李四" + i)
					.field("gender", gender).field("address", "海淀" + i).field("userName", "张三" + i)
					.field("password", "123" + i).field("email", "da" + i + "@123.com").endObject();
			prepareIndex.setSource(xContentBuilder);
			IndexResponse indexResponse = prepareIndex.get();
			logger.info(indexResponse.getId());
		}
		return "成功";
	}

	/**
	 * @Title: deleteByQuery
	 * @author: zhb
	 * @date: 2017年7月28日 上午11:52:21
	 * @Description: 删除指定条件的数据
	 * @return
	 * @throws IOException
	 */
	@RequestMapping("deleteByQuery")
	public String deleteByQuery() throws IOException {
		BulkByScrollResponse response = DeleteByQueryAction.INSTANCE.newRequestBuilder(transportClient)
				.filter(matchQuery("gender", 1)).source("users").get();
		long deleted = response.getDeleted();
		logger.info("删除成功" + deleted);
		return "成功";
	}

	/**
	 * @Title: asyDeleteByQuery
	 * @author: zhb
	 * @date: 2017年7月28日 上午11:55:16
	 * @Description: 异步删除并提供监听
	 * @return
	 * @throws IOException
	 */
	@RequestMapping("asyDeleteByQuery")
	public String asyDeleteByQuery() throws IOException {
		DeleteByQueryAction.INSTANCE.newRequestBuilder(transportClient).filter(matchQuery("gender", "0"))
				.source("users").execute(new ActionListener<BulkByScrollResponse>() {
					@Override
					public void onResponse(BulkByScrollResponse response) {
						long deleted = response.getDeleted();
						logger.info("删除成功" + deleted);
					}

					@Override
					public void onFailure(Exception e) {
						// Handle the exception
						// 删除失败
						logger.info("删除失败");
					}
				});
		return "成功";
	}

	/**
	 * @Title: multiGetItem
	 * @author: zhb
	 * @date: 2017年7月28日 下午2:56:58
	 * @Description: 根据条件一次查询多条记录
	 * @return
	 * @throws IOException
	 */
	@RequestMapping("multiGetItem")
	public String multiGetItem() throws IOException {
		MultiGetResponse multiGetResponse = transportClient.prepareMultiGet().add("articles", "article", "1")
				.add("users", "user").get();
		for (MultiGetItemResponse multiGetItemResponse : multiGetResponse) {
			GetResponse response = multiGetItemResponse.getResponse();
			if (response.isExists()) {
				logger.info(response.getSourceAsString());
			}
		}
		return "成功";
	}

	/**
	 * @Title: bulkSearch
	 * @author: zhb
	 * @date: 2017年7月28日 下午3:02:53
	 * @Description: 批量操作 批量API允许在单个请求中对多个文档进行索引和删除。
	 * @return
	 * @throws IOException
	 */
	@RequestMapping("bulkSearch")
	public String bulkSearch() throws IOException {
		BulkRequestBuilder bulkRequest = transportClient.prepareBulk();

		// index/delete requests
		bulkRequest.add(transportClient.prepareIndex("users", "user").setSource(jsonBuilder().startObject()
				.field("userName", "李四1").field("registerTime", new Date()).field("address", "北京市海淀区").endObject()));

		bulkRequest.add(transportClient.prepareIndex("twitter", "tweet", "2").setSource(jsonBuilder().startObject()
				.field("user", "kimchy").field("postDate", new Date()).field("message", "another post").endObject()));

		BulkResponse bulkResponse = bulkRequest.get();
		if (bulkResponse.hasFailures()) {
		}
		return "成功";
	}

	/**
	 * @Title: bulkSearch
	 * @author: zhb
	 * @date: 2017年7月28日 下午3:02:53
	 * @Description: 批量操作 批量API允许在单个请求中对多个文档进行索引和删除。类似存储过程一样,一次操作多项
	 * @return
	 * @throws IOException
	 */
	@RequestMapping("bulkProcessor")
	public String bulkProcessor() throws IOException {
		BulkProcessor bulkProcessor = BulkProcessor.builder(transportClient, new BulkProcessor.Listener() {
			@Override
			public void beforeBulk(long executionId, BulkRequest request) {
				// bulk 之前执行
				int numberOfActions = request.numberOfActions();
				logger.info("" + numberOfActions);
			}

			@Override
			public void afterBulk(long executionId, BulkRequest request, BulkResponse response) {
				// bulk 之后执行
				boolean hasFailures = response.hasFailures();
				logger.info("" + hasFailures);

			}

			@Override
			public void afterBulk(long executionId, BulkRequest request, Throwable failure) {
				// bulk 抛出异常的时候执行

			}
		}).setBulkActions(10000).setBulkSize(new ByteSizeValue(5, ByteSizeUnit.MB))
				.setFlushInterval(TimeValue.timeValueSeconds(5)).setConcurrentRequests(1)
				.setBackoffPolicy(BackoffPolicy.exponentialBackoff(TimeValue.timeValueMillis(100), 3)).build();
		return "成功";
	}

	/**
	 * @Title: search
	 * @author: zhb
	 * @date: 2017年7月28日 下午3:59:11
	 * @Description: 简单查询
	 * @return
	 * @throws IOException
	 */
	@RequestMapping("search")
	public String search() throws IOException {
		String[] indices = new String[] { "users" };
		String[] types = new String[] { "user" };
		SearchResponse searchResponse = transportClient.prepareSearch(indices).setTypes(types)
				.setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setQuery(termQuery("userName", "张三5")).setFrom(0)
				.setSize(10).setExplain(true).get();
		logger.info(searchResponse.getHits() + "");
		return "成功";
	}

	/**
	 * @Title: search
	 * @author: zhb
	 * @date: 2017年7月28日 下午3:59:11
	 * @Description: 简单查询
	 * @return
	 * @throws IOException
	 */
	@RequestMapping("scrollsSearch")
	public String scrollsSearch() throws IOException {
		String[] indices = new String[] { "users" };
		String[] types = new String[] { "user" };
		QueryBuilder qb = termQuery("multi", "test");
		// 如果设置，将启用对指定超时的搜索请求的滚动。
		SearchResponse response = transportClient.prepareSearch(indices)
				.addSort(FieldSortBuilder.DOC_FIELD_NAME, SortOrder.ASC).setScroll(new TimeValue(60000))
				.setQuery(termQuery("userName", "张三5")).get();
		do {
			for (SearchHit hit : response.getHits().getHits()) {
				logger.info(hit.getId() + "");
			}
			response = transportClient.prepareSearchScroll(response.getScrollId()).setScroll(new TimeValue(60000))
					.execute().actionGet();
		} while (response.getHits().getHits().length != 0);

		return "成功";
	}

	/**
	 * @Title: search
	 * @author: zhb
	 * @date: 2017年7月28日 下午3:59:11
	 * @Description: 多条件组合查询
	 * @return
	 * @throws IOException
	 */
	@RequestMapping("multiSearch")
	public String multiSearch() throws IOException {
		SearchRequestBuilder builder1 = transportClient.prepareSearch().setQuery(queryStringQuery("elasticsearch"))
				.setSize(1);
		SearchRequestBuilder builder2 = transportClient.prepareSearch().setQuery(matchQuery("userName", "张三"))
				.setSize(1);
		MultiSearchResponse searchResponse = transportClient.prepareMultiSearch().add(builder1).add(builder2).get();
		long nbHits = 0;
		for (MultiSearchResponse.Item item : searchResponse.getResponses()) {
			SearchResponse response = item.getResponse();
			nbHits += response.getHits().getTotalHits();
		}
		return "成功";
	}

	/**
	 * @Title: search
	 * @author: zhb
	 * @date: 2017年7月28日 下午3:59:11
	 * @Description: TODO
	 * @return
	 * @throws IOException
	 */
	@RequestMapping("aggregations")
	public String aggregations() throws IOException {
		SearchResponse searchResponse = transportClient.prepareSearch().setQuery(QueryBuilders.matchAllQuery())
				.addAggregation(terms("agg1").field("field"))
				.addAggregation(dateHistogram("agg2").field("birth").dateHistogramInterval(DateHistogramInterval.YEAR))
				.get();
		Terms agg1 = searchResponse.getAggregations().get("agg1");

		DateHistogramInterval agg2 = searchResponse.getAggregations().get("agg2");
		return "成功";
	}

	/**
	 * @Title: terminateAfter
	 * @author: zhb
	 * @date: 2017年7月31日 下午10:13:05
	 * @Description: TODO 每个分片收集的最大文档数量，到达查询执行将提前终止。 如果设置，您可以通过在SearchResponse
	 *               onject中询问isTerminatedEarly（）来检查操作是否提前终止：
	 * @return
	 * @throws IOException
	 */
	@RequestMapping("terminateAfter")
	public String terminateAfter() throws IOException {
		SearchResponse sr = transportClient.prepareSearch("users").setTerminateAfter(1000).get();
		if (sr.isTerminatedEarly()) {

		}
		return "成功";
	}

	/**
	 * @Title: searchTemplate
	 * @author: zhb
	 * @date: 2017年7月31日 下午10:19:14
	 * @Description: 构建查询模板查询
	 * @return
	 * @throws IOException
	 */
	@RequestMapping("searchTemplate")
	public String searchTemplate() throws IOException {
		Map<String, Object> template_params = new HashMap<>();
		template_params.put("param_gender", "male");
		SearchResponse sr = new SearchTemplateRequestBuilder(transportClient).setScript("template_gender")
				.setScriptType(ScriptType.FILE).setScriptParams(template_params).setRequest(new SearchRequest()).get()
				.getResponse();
		return "";
	}

	@RequestMapping("findAll")
	public String findAll() {
		List<User> list = userService.findAll();
		System.out.println(transportClient.admin().toString());
		return list.get(0).toString();
	}
}
